import { OnQueueFailed, Process, Processor } from '@nestjs/bull';
import { Injectable } from '@nestjs/common';
import { Job } from 'bull';
import { NotifyService } from './notify.service';
import { PUSH_STATUS, QUEUE_CONFIG } from './config';

@Processor('notify')
@Injectable()
export class NotifyQueueConsumer {
  constructor(
    private notifyService: NotifyService
  ) { }

  /**
   * 处理可靠推送批次
   */
  @Process('reliable-push-batch')
  async processReliablePushBatch(job: Job) {
    const { notifyIds = [] } = job.data;
    if (!Array.isArray(notifyIds) || notifyIds.length === 0) return;
    // 查询待推送的通知记录
    const notifies = await this.notifyService.findNotifyByIds(notifyIds);
    if (notifies.length === 0) return;

    // 并发推送
    const CONCURRENT_LIMIT = QUEUE_CONFIG.RELIABLE_PUSH_CONCURRENT_LIMIT;
    const successfulNotifyIds: number[] = [];
    let failedCount = 0;

    for (let i = 0; i < notifies.length; i += CONCURRENT_LIMIT) {
      const batch = notifies.slice(i, i + CONCURRENT_LIMIT);
      const results = await Promise.allSettled(
        batch.map(notify => this.notifyService.toSend(notify))
      );

      // 收集成功推送的通知ID
      results.forEach((result, index) => {
        if (result.status === 'fulfilled') {
          successfulNotifyIds.push(batch[index].id);
        } else {
          failedCount++;
        }
      });
    }

    // 批量更新成功推送的通知状态
    if (successfulNotifyIds.length > 0) {
      try {
        await this.notifyService.batchUpdateNotifyStatus(successfulNotifyIds, PUSH_STATUS.SUCCESS);
      } catch (error) {
        // 如果批量更新失败，抛出错误触发重试
        throw new Error(`批量更新状态失败: ${error.message}`);
      }
    }

    // 如果有推送失败的，抛出错误触发重试
    if (failedCount > 0) throw new Error(`有 ${failedCount} 个通知推送失败`);
  }

  /**
   * 处理即时推送批次
   */
  @Process('instant-push-batch')
  async processInstantPushBatch(job: Job) {
    const { data = [] } = job.data;
    if (!Array.isArray(data) || data.length === 0) return;

    // 并发推送
    const CONCURRENT_LIMIT = QUEUE_CONFIG.INSTANT_PUSH_CONCURRENT_LIMIT;
    let failedCount = 0;

    for (let i = 0; i < data.length; i += CONCURRENT_LIMIT) {
      const batch = data.slice(i, i + CONCURRENT_LIMIT);
      const results = await Promise.allSettled(
        batch.map(item => this.notifyService.toSend(item))
      );

      failedCount += results.filter(r => r.status === 'rejected').length;
    }

    // 如果有失败，触发重试
    if (failedCount > 0) throw new Error(`即时推送有 ${failedCount} 个失败`);
  }

  /**
   * 队列任务失败处理
   */
  @OnQueueFailed()
  async onQueueFailed(job: Job) {
    if (job.name === 'reliable-push-batch') {
      await this.handleReliablePushFinalFailure(job.data);
    }
    // 即时推送失败无需处理
  }

  /**
   * 处理可靠推送的最终失败
   */
  private async handleReliablePushFinalFailure(jobData: any): Promise<void> {
    const { notifyIds = [] } = jobData;

    if (!Array.isArray(notifyIds) || notifyIds.length === 0) return;

    try {
      await this.notifyService.batchUpdateNotifyStatus(notifyIds, PUSH_STATUS.FAILED);
    } catch (error) {
      // 静默处理错误，不记录日志
    }
  }
}
